output_parameter.hpp
namespace type_safe
{
template <typename T>
class output_parameter;
template <typename T>
output_parameter<T> out(T& obj) noexcept;
template <typename T>
output_parameter<T> out(deferred_construction<T>& o) noexcept;
}
type_safe::output_parameter
template <typename T>
class output_parameter
{
public:
using parameter_type = T;
output_parameter(T& obj) noexcept;
output_parameter(const T&) = delete;
output_parameter(T&&) = delete;
output_parameter(const T&&) = delete;
output_parameter(deferred_construction<T>& out) noexcept;
output_parameter(const deferred_construction<T>&) = delete;
output_parameter(deferred_construction<T>&&) = delete;
output_parameter(const deferred_construction<T>&&) = delete;
output_parameter(output_parameter&& other) noexcept;
~output_parameter() noexcept = default;
output_parameter& operator=(const output_parameter&) = delete;
output_parameter& operator=(output_parameter&&) = delete;
template <typename U>
typename std::enable_if<std::is_constructible<T, decltype(std::forward<U>(u))>::value, parameter_type&>::type operator=(U&& u);
template <typename ... Args>
T& assign(Args&&... args);
};
A tiny wrapper modelling an output parameter of a function.
An output parameter is a parameter that will be used to transport output of a function to its caller, like a return value does. Usually they are implemented with lvalue references. They have a couple of disadvantages though:
If you use this class as your output parameter type, you do not have these disadvantages. The creation is explicit, you cannot read the value, and it works with ts::deferred_construction.
Notes: While you could use this class in other locations besides parameters, this is not recommended.
type_safe::output_parameter::output_parameter
output_parameter(T& obj) noexcept;
Effects: Creates it from an lvalue reference. All output will be assigned to the object referred by the reference.
Requires: The referred object must live as long as the function has not returned.
type_safe::output_parameter::output_parameter
(1) output_parameter(const T&) = delete;
(2) output_parameter(T&&) = delete;
(3) output_parameter(const T&&) = delete;
type_safe::output_parameter::output_parameter
output_parameter(deferred_construction<T>& out) noexcept;
Effects: Creates it from a ts::deferred_construction object. All output will be assigned or created in the storage of the defer construction object, depending on wheter it is initialized.
Requires: The referred object must live as long as the function has not returned.
type_safe::output_parameter::output_parameter
(1) output_parameter(const deferred_construction<T>&) = delete;
(2) output_parameter(deferred_construction<T>&&) = delete;
(3) output_parameter(const deferred_construction<T>&&) = delete;
type_safe::output_parameter::output_parameter
output_parameter(output_parameter&& other) noexcept;
Effects: Moves an output parameter. This will put other
in an invalid state, it must not be used afterwards.
Notes: This constructor is only there because guaranteed copy elision isn't available and otherwise the out()
function could not be implemented. It is not intended to use it otherwise.
type_safe::output_parameter::operator=
(1) output_parameter& operator=(const output_parameter&) = delete;
(2) output_parameter& operator=(output_parameter&&) = delete;
type_safe::output_parameter::operator=
template <typename U>
typename std::enable_if<std::is_constructible<T, decltype(std::forward<U>(u))>::value, parameter_type&>::type operator=(U&& u);
Effects: Same as assign(std::forward<U>(u))
.
Returns: A reference to the value that was assigned, not *this
as normal "assignment" operators. \requires value_type
must be constructible from U
. \synopsis_return parameter_type&
type_safe::out
template <typename T>
output_parameter<T> out(T& obj) noexcept;
Returns: A new ts::output_parameter using the reference obj
as output.
type_safe::out
template <typename T>
output_parameter<T> out(deferred_construction<T>& o) noexcept;
Returns: A new ts::output_parameter using the ts::deferred_construction as output.